package cc.android.testapp.xp;

import android.content.Context;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Enumeration;

import cc.android.testapp.util.CLog;
import cc.commons.util.FileUtil;
import cc.commons.util.reflect.ClassUtil;
import cc.commons.util.reflect.FieldUtil;
import cc.commons.util.reflect.MethodUtil;
import dalvik.system.DexFile;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;

public class XPTool {
    public static XC_MethodHook.Unhook hookNoErr(Class<?> clazz, String methodName, Object... parameterTypesAndCallback) {
        try {
            return XposedHelpers.findAndHookMethod(clazz, methodName, parameterTypesAndCallback);
        } catch (Throwable e) {
            CLog.log("Error on hook", e);
        }
        return null;
    }

    /**
     * 检索指定包下的所有类
     *
     * @param pLoader 类加载器
     * @param pPackge 包名,以点分割
     * @param pChild  是否包括子目录下的类
     * @return 所有符合的类
     */
    public static ArrayList<Class<?>> getPackgeClass(ClassLoader pLoader, String pPackge, boolean pChild) {
        ArrayList<Class<?>> pClazzs = new ArrayList<>();
        try {
            Object dexPathList = FieldUtil.getFieldValue(ClassUtil.getClass("dalvik.system.BaseDexClassLoader"), "pathList", pLoader);
            Object[] dexElements = (Object[]) FieldUtil.getFieldValue(dexPathList.getClass(), "dexElements", dexPathList);
            for (Object dexElement : dexElements) {
                DexFile tDFile = (DexFile) FieldUtil.getFieldValue(dexElement.getClass(), "dexFile", dexElement);
                Enumeration<String> tEntry = tDFile.entries();
                while (tEntry.hasMoreElements()) {
                    String tName = tEntry.nextElement();
                    if (tName.startsWith(pPackge)) {
                        if (pChild || tName.indexOf('.', pPackge.length() + 1) == -1) {
                            pClazzs.add(pLoader.loadClass(tName));
                        }
                    }
                }
            }
        } catch (Throwable e) {
            CLog.log("检索包\"" + pPackge + "\"下的类时出错", e);
        }
        return pClazzs;
    }
}
